package com.me.study.socket.io;

import com.me.common.util.SleepUtil;
import org.apache.commons.lang3.RandomUtils;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * Socket编程：服务端
 *
 * @author ME
 * @date   2019/4/26
 */
public class SocketServer {

    /**
     * TODO 预定义的消息结束符，缺了的话，字节流会一直阻塞无法终止
     */
    public static final String EOF = "eof";
    public static final String END = EOF + System.lineSeparator();

    public static void main(String args[]) throws IOException {
        //为了简单起见，所有的异常信息都往外抛
        int port = 8899;
        //定义一个ServerSocket监听在端口8899上
        ServerSocket server = new ServerSocket(port);
        server.setSoTimeout(10000);
        while (true) {
            //server尝试接收其他Socket的连接请求，server的accept方法是阻塞式的
            Socket socket = server.accept();
            //每接收到一个Socket就建立一个新的线程来处理它
            new Thread(new Task(socket)).start();
        }
    }

    /**
     * 用来处理Socket请求的
     */
    static class Task implements Runnable {
        private final Socket socket;
        public Task(Socket socket) {
            this.socket = socket;
        }

        @Override
        public void run() {
            try {
                handleSocket();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        /**
         * 跟客户端 Socket 进行通信
         */
        private void handleSocket() throws Exception {
            BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            StringBuilder msg = new StringBuilder();
            String inputLine;
            int index;
            while ((inputLine = reader.readLine()) != null) {
                // 遇到eof时就结束接收
                if ((index = inputLine.indexOf(EOF)) != -1) {
                    msg.append(inputLine, 0, index);
                    break;
                }
                msg.append(inputLine);
            }
            SleepUtil.seconds(RandomUtils.nextInt(2, 4));
            System.out.println("from client: " + msg);

            // 读完所有消息后回复
            PrintWriter writer = new PrintWriter(socket.getOutputStream(), true);
            writer.println("Hello Client. " + msg);
            writer.println(END);

            // TODO 应该调用 socket.close 自动关闭 IO流，避免不可预期的错误
            // writer.close();reader.close();
            socket.close();
        }
    }
}
